package com.example.order.service;

import com.example.order.messaging.message.OrderCreatedMessage;
import com.example.order.messaging.producer.OrderEventProducer;
import com.example.order.model.dto.CreateOrderRequest;
import com.example.order.model.dto.OrderResponse;
import com.example.order.model.entity.Order;
import com.example.order.model.entity.OrderItem;
import com.example.order.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 * 
 * @author mall-team
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final OrderEventProducer orderEventProducer;

    /**
     * 创建订单
     * 1. 保存订单到数据库
     * 2. 发送订单创建事件到 Kafka
     * 
     * @param request 创建订单请求
     * @return 订单响应
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderResponse createOrder(CreateOrderRequest request) {
        log.info("开始创建订单: userId={}", request.getUserId());

        // 1. 生成订单编号
        String orderNo = generateOrderNo();

        // 2. 计算订单总金额
        BigDecimal totalAmount = calculateTotalAmount(request.getItems());

        // 3. 构建订单实体
        Order order = Order.builder()
                .orderNo(orderNo)
                .userId(request.getUserId())
                .totalAmount(totalAmount)
                .status("PENDING")  // 初始状态：待支付
                .shippingAddress(request.getShippingAddress())
                .remark(request.getRemark())
                .build();

        // 4. 构建订单明细
        List<OrderItem> orderItems = request.getItems().stream()
                .map(itemReq -> {
                    BigDecimal price = new BigDecimal(itemReq.getPrice());
                    BigDecimal subtotal = price.multiply(new BigDecimal(itemReq.getQuantity()));
                    
                    return OrderItem.builder()
                            .skuId(itemReq.getSkuId())
                            .skuName(itemReq.getSkuName())
                            .price(price)
                            .quantity(itemReq.getQuantity())
                            .subtotal(subtotal)
                            .build();
                })
                .collect(Collectors.toList());

        // 5. 关联订单和明细
        orderItems.forEach(order::addItem);

        // 6. 保存订单（级联保存订单明细）
        Order savedOrder = orderRepository.save(order);
        log.info("订单保存成功: orderNo={}, orderId={}", orderNo, savedOrder.getId());

        // 7. 发送订单创建事件
        OrderCreatedMessage message = buildOrderCreatedMessage(savedOrder);
        orderEventProducer.sendOrderCreatedEvent(message);

        // 8. 返回订单响应
        return convertToResponse(savedOrder);
    }

    /**
     * 根据订单编号查询订单
     * 
     * @param orderNo 订单编号
     * @return 订单响应
     */
    @Transactional(readOnly = true)
    public OrderResponse getOrderByOrderNo(String orderNo) {
        log.info("查询订单: orderNo={}", orderNo);
        
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderNo));
        
        return convertToResponse(order);
    }

    /**
     * 更新订单状态为已支付
     * 
     * @param orderNo 订单编号
     * @param paymentNo 支付流水号
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatusToPaid(String orderNo, String paymentNo) {
        log.info("更新订单状态为已支付: orderNo={}, paymentNo={}", orderNo, paymentNo);
        
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderNo));
        
        // 更新订单状态
        order.setStatus("PAID");
        orderRepository.save(order);
        
        log.info("订单状态更新成功: orderNo={}, status=PAID", orderNo);
    }

    /**
     * 生成订单编号
     * 格式: ORD + 时间戳 + UUID前8位
     */
    private String generateOrderNo() {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return "ORD" + timestamp + uuid;
    }

    /**
     * 计算订单总金额
     */
    private BigDecimal calculateTotalAmount(List<CreateOrderRequest.OrderItemRequest> items) {
        return items.stream()
                .map(item -> {
                    BigDecimal price = new BigDecimal(item.getPrice());
                    return price.multiply(new BigDecimal(item.getQuantity()));
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 构建订单创建消息
     */
    private OrderCreatedMessage buildOrderCreatedMessage(Order order) {
        List<OrderCreatedMessage.OrderItemInfo> itemInfos = order.getItems().stream()
                .map(item -> OrderCreatedMessage.OrderItemInfo.builder()
                        .skuId(item.getSkuId())
                        .skuName(item.getSkuName())
                        .quantity(item.getQuantity())
                        .price(item.getPrice())
                        .subtotal(item.getSubtotal())
                        .build())
                .collect(Collectors.toList());

        return OrderCreatedMessage.builder()
                .orderNo(order.getOrderNo())
                .userId(order.getUserId())
                .totalAmount(order.getTotalAmount())
                .items(itemInfos)
                .build();
    }

    /**
     * 转换为订单响应 DTO
     */
    private OrderResponse convertToResponse(Order order) {
        List<OrderResponse.OrderItemResponse> itemResponses = order.getItems().stream()
                .map(item -> OrderResponse.OrderItemResponse.builder()
                        .id(item.getId())
                        .skuId(item.getSkuId())
                        .skuName(item.getSkuName())
                        .price(item.getPrice())
                        .quantity(item.getQuantity())
                        .subtotal(item.getSubtotal())
                        .build())
                .collect(Collectors.toList());

        return OrderResponse.builder()
                .id(order.getId())
                .orderNo(order.getOrderNo())
                .userId(order.getUserId())
                .totalAmount(order.getTotalAmount())
                .status(order.getStatus())
                .shippingAddress(order.getShippingAddress())
                .remark(order.getRemark())
                .createdAt(order.getCreatedAt())
                .updatedAt(order.getUpdatedAt())
                .items(itemResponses)
                .build();
    }
}

